﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Web;

using BingMapsSample.BingMaps.GeocodingService;
using BingMapsSample.BingMaps.RoutingService;
using BingMapsSample.BingMaps.SearchingService;

namespace BingMapsSample.Components
{
    public class BingMapsService
    {
        //------// Properties \\--------------------------------------------\\
        private string _applicationID = null;
        public string ApplicationID
        {
            get
            {
                if (_applicationID == null)
                {
                    _applicationID = ConfigurationManager.AppSettings["Bing Maps Application ID"] ?? String.Empty;
                }

                return _applicationID;
            }
        }
        //------\\ Properties //--------------------------------------------//



        //------// Constructors \\------------------------------------------\\
        public BingMapsService()
        { }
        //------\\ Constructors //------------------------------------------//



        //------// Methods \\-----------------------------------------------\\
        public Location GeocodeAddress(string address)
        {
            Location location = null;

            GeocodeRequest geocodingRequest = new GeocodeRequest();

            geocodingRequest.Credentials = new BingMapsSample.BingMaps.GeocodingService.Credentials();
            geocodingRequest.Credentials.ApplicationId = ApplicationID;

            geocodingRequest.Query = address;

            
            GeocodeResponse geocodingResponse = new GeocodeServiceClient().Geocode(geocodingRequest);
            
            if (geocodingResponse.Results.Length > 0)
            {
                location = new Location();

                if (geocodingResponse.Results[0].Confidence == BingMapsSample.BingMaps.GeocodingService.Confidence.Low)
                {
                    location.Coordinate = null;
                }
                else
                {
                    Coordinate coordinate = new Coordinate();
                    coordinate.Latitude = geocodingResponse.Results[0].Locations[0].Latitude;
                    coordinate.Longitude = geocodingResponse.Results[0].Locations[0].Longitude;

                    location.Coordinate = coordinate;
                }


                Address returnedAddress = new Address();
                returnedAddress.Address1 = geocodingResponse.Results[0].Address.AddressLine;
                returnedAddress.City = geocodingResponse.Results[0].Address.Locality;
                returnedAddress.State = geocodingResponse.Results[0].Address.AdminDistrict;
                returnedAddress.ZipCode = geocodingResponse.Results[0].Address.PostalCode;

                location.Address = returnedAddress;
            }


            return location;
        }


        public Location GeocodeIPAddress(string ipAddress)
        {
            Location location = null;

            GeocodeRequest geocodingRequest = new GeocodeRequest();

            geocodingRequest.Credentials = new BingMapsSample.BingMaps.GeocodingService.Credentials();
            geocodingRequest.Credentials.ApplicationId = ApplicationID;

            geocodingRequest.Query = ipAddress;


            GeocodeResponse geocodingResponse = new GeocodeServiceClient().Geocode(geocodingRequest);

            if (geocodingResponse.Results.Length > 0)
            {
                location = new Location();

                if (geocodingResponse.Results[0].Confidence == BingMapsSample.BingMaps.GeocodingService.Confidence.Low)
                {
                    location.Coordinate = null;
                }
                else
                {
                    Coordinate coordinate = new Coordinate();
                    coordinate.Latitude = geocodingResponse.Results[0].Locations[0].Latitude;
                    coordinate.Longitude = geocodingResponse.Results[0].Locations[0].Longitude;

                    location.Coordinate = coordinate;
                }


                Address returnedAddress = new Address();
                returnedAddress.Address1 = geocodingResponse.Results[0].Address.AddressLine;
                returnedAddress.City = geocodingResponse.Results[0].Address.Locality;
                returnedAddress.State = geocodingResponse.Results[0].Address.AdminDistrict;
                returnedAddress.ZipCode = geocodingResponse.Results[0].Address.PostalCode;

                location.Address = returnedAddress;
            }


            return location;
        }


        public List<Place> KeywordSearch(string keyword)
        {
            List<Place> places = new List<Place>();

            SearchRequest searchingRequest = new SearchRequest();

            searchingRequest.Credentials = new BingMapsSample.BingMaps.SearchingService.Credentials();
            searchingRequest.Credentials.ApplicationId = ApplicationID;

            searchingRequest.Query = keyword;

            searchingRequest.SearchOptions = new SearchOptions();
            searchingRequest.SearchOptions.Count = 25;


            SearchResponse searchingResponse = new SearchServiceClient().Search(searchingRequest);

            if (searchingResponse.ResultSets.Length > 0)
            {
                foreach (SearchResultBase result in searchingResponse.ResultSets[0].Results)
                {
                    Place place = new Place();
                    place.Name = result.Name;

                    Location location = new Location();


                    // Set the Address of the result.
                    switch (result.GetType().Name)
                    {
                        case "BusinessSearchResult":

                            BusinessSearchResult businessResult = (BusinessSearchResult)result;

                            place.PhoneNumber = businessResult.PhoneNumber;

                            if (businessResult.Website != null)
                            {
                                place.Website = businessResult.Website.ToString();
                            }

                            Address address = new Address();
                            address.Address1 = businessResult.Address.AddressLine;
                            address.City = businessResult.Address.Locality;
                            address.State = businessResult.Address.AdminDistrict;
                            address.ZipCode = businessResult.Address.PostalCode;
                            
                            location.Address = address;

                            break;

                        case "CommunityContentSearchResult":

                            CommunityContentSearchResult communityResult = (CommunityContentSearchResult)result;

                            place.Description = communityResult.Description;

                            break;

                        case "PersonSearchResult":

                            PersonSearchResult personResult = (PersonSearchResult)result;

                            place.PhoneNumber = personResult.PhoneNumber;

                            address = new Address();
                            address.Address1 = personResult.Address.AddressLine;
                            address.City = personResult.Address.Locality;
                            address.State = personResult.Address.AdminDistrict;
                            address.ZipCode = personResult.Address.PostalCode;
                            
                            location.Address = address;

                            break;
                    }


                    // Set the Coordinate of the result.
                    Coordinate coordinate = new Coordinate();
                    coordinate.Latitude = result.LocationData.Locations[0].Latitude;
                    coordinate.Longitude = result.LocationData.Locations[0].Longitude;

                    location.Coordinate = coordinate;

                    place.Location = location;
                    places.Add(place);
                }
            }

            return places;
        }
        //------\\ Methods //-----------------------------------------------//
    }
}
